
#ifndef _ga_random_h_
#define _ga_random_h_

#include <stdlib.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>

class GARandom 
	{
	private:
	const gsl_rng_type * T;
	gsl_rng * r;

	public:
	GARandom(long seed) {
	      gsl_rng_env_setup();
       	      T = gsl_rng_default;
       	      r = gsl_rng_alloc (T);
	      gsl_rng_set (r, seed);
	      }
	~GARandom() {
		gsl_rng_free (r);
		}

	inline int GARandomInt(){ 
		return gsl_rng_uniform (r) > 0.5 ? 1 : 0; 
		}
	inline int GARandomInt(int low, int high){
		return (int) (low + gsl_rng_uniform (r) * (high-low)); 
		}

	inline double GARandomDouble(){ 
		double f = gsl_rng_uniform(r);
		return f; 
		}
	inline double GARandomDouble(double low, double high){
  		double val=high-low; val*=gsl_rng_uniform (r); return val+low;
		}

	inline float GARandomFloat(){ 
		return gsl_rng_uniform (r); 
		}
	inline float GARandomFloat(float low, float high){
  		float val=high-low; val*=gsl_rng_uniform (r); return val+low;
		}

	inline double GAUnitGaussian() {
		return gsl_ran_ugaussian(r);
		}

	inline bool GAFlipCoin(float p){
		  return((p == 1.0) ? true : (p == 0.0) ? false :
			 ((GARandomFloat() <= p) ? true : false));
		  }

	inline float GAGaussianFloat(float dev){ 
		return (float)gsl_ran_gaussian (r, dev); 
		}

	inline double GAGaussianDouble(double dev){ 
		return (float)gsl_ran_gaussian (r, dev); 
		}

	};

#endif
